import axios, {AxiosResponse} from 'axios'
import type {AxiosInstance} from 'axios'
import type {CVRequestConfig, CVRequestInterceptors} from './type'
import {ElLoading} from 'element-plus'
import {ILoadingInstance} from 'element-plus/lib/el-loading/src/loading.type'

class CVRequest {
  instance: AxiosInstance
  interceptors?: CVRequestInterceptors
  showLoading: boolean
  loading?: ILoadingInstance

  // 类的构造器
  constructor(config: CVRequestConfig) {
    this.instance = axios.create(config)
    this.showLoading = config.showLoading ?? true
    this.interceptors = config.interceptors

    // request拦截器
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptors,
      this.interceptors?.requestInterceptorsCatch
    )

    // response拦截器
    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptors,
      this.interceptors?.responseInterceptorsCatch
    )

    // 添加所有实例都有的拦截器
    this.instance.interceptors.request.use((config) => {
        this.loading = ElLoading.service({
          lock: true,
          background: 'var(--bg-nspa)',
          text: '数据请求中...'
        })
        return config
      }, (err) => {
        return err
      }
    )

    this.instance.interceptors.response.use(
      (res) => {
        // 移除loading
        this.loading?.close()

        // @ts-ignore
        if (res.code !== 20000) {
          // TODO 页面显示错误信息
        } else {
          return res.data
        }
        return config
      }, (err) => {
        // 移除loading
        this.loading?.close()

        // TODO
        let message = showStatus(err.response.status)
        if (err.response.status === 404) {
          console.log('404的错误~')
        }
        return err
      }
    )
  }

  request<T>(config: CVRequestConfig<T>): Promise<T> {
    return new Promise((resolve, reject) => {
      if (config.interceptors?.requestInterceptors) {
        config = config.interceptors?.requestInterceptors(config)
      }

      if (config.showLoading === false) {
        this.showLoading = config.showLoading
      }

      this.instance.request<any, T>(config)
        .then((res) => {
          // 1.单个请求对数据的处理
          if (config.interceptors?.responseInterceptors) {
            res = config.interceptors.responseInterceptors(res)
          }

          // 2.将showLoading值重置，不影响下一次请求
          this.showLoading = true

          resolve(res)
        }).catch(err => {
        this.showLoading = true
        reject(err)
        return err
      })
    })
  }

  get<T>(cofing: CVRequestConfig<T>): Promise<T> {
    return this.request<T>({...cofing, method: 'GET'})
  }

  post<T>(cofing: CVRequestConfig<T>): Promise<T> {
    return this.request<T>({...cofing, method: 'POST'})
  }

  put<T>(cofing: CVRequestConfig<T>): Promise<T> {
    return this.request<T>({...cofing, method: 'PUT'})
  }

  delete<T>(cofing: CVRequestConfig<T>): Promise<T> {
    return this.request<T>({...cofing, method: 'DELETE'})
  }
}

const showStatus = (status: number) => {
  let message = ''
  switch (status) {
    case 400:
      message = '请求错误(400)'
      break
    case 401:
      message = '未授权，请重新登录(401)'
      break
    case 403:
      message = '拒绝访问(403)'
      break
    case 404:
      message = '请求出错(404)'
      break
    case 408:
      message = '请求超时(408)'
      break
    case 500:
      message = '服务器错误(500)'
      break
    case 501:
      message = '服务未实现(501)'
      break
    case 502:
      message = '网络错误(502)'
      break
    case 503:
      message = '服务不可用(503)'
      break
    case 504:
      message = '网络超时(504)'
      break
    case 505:
      message = 'HTTP版本不受支持(505)'
      break
    default:
      message = `连接出错(${status})!`
  }
  return `${message}，请检查网络或联系管理员！`
}
export default CVRequest
